package producersConsumersTests;

import java.util.HashMap;
import java.util.Map;

import prod_cons.TaskContainer;
import producersConsumersTests.InserterThroughput.InsertionThroughputTest;
import producersConsumersTests.RemoverThroughput.RemoverThroughputTest;
import producersConsumersTests.WaitingTime.TimedTask;
import producersConsumersTests.WaitingTime.WaitingTimeTest;
import producersConsumersTests.bypassersCount.BypassCountTestV2;
import producersConsumersTests.meanInsertionTime.MeanInsertionTimeTest;
import producersConsumersTests.meanRemovalTime.MeanRemovalTimeTest;
import producersConsumersTests.results.ResultPrinter;
import producersConsumersTests.utils.Test;
import producersConsumersTests.utils.Inserter.ArrivalType;

/**
 * The main test program Gets arguments from the user, and launches all 5 tests
 * using them.
 * 
 * Well, to put long thing short, this following line concerns all classes:
 * 
 * @requires EVERYTHING != null, valid arguments, etc.
 */
public class Main {
	private static Map<Integer, Test> testers = new HashMap<Integer, Test>();

	public static void main(String args[]) throws InstantiationException,
			IllegalAccessException, ClassNotFoundException {
		testers.put(1, new InsertionThroughputTest());
		testers.put(2, new RemoverThroughputTest());
		testers.put(3, new MeanInsertionTimeTest());
		testers.put(4, new MeanRemovalTimeTest());
		// before insertion, after removal
		testers.put(5, new WaitingTimeTest(TimedTask.WhenToMeasure.BEFORE,
				TimedTask.WhenToMeasure.AFTER));
		// after insertion, before removal
		testers.put(6, new WaitingTimeTest(TimedTask.WhenToMeasure.AFTER,
				TimedTask.WhenToMeasure.BEFORE));
		testers.put(7, new BypassCountTestV2());
		try {
			// default values;
			int testNum = 7, insertersNum = 8, removersNum = 8, peakLength = 10000;
			int timeBetweenPeaks = 100, timeToRun = 1000, extraInt = 1000, superIndex = 0;
			double lambda = 0.5;
			String filename = "";
			ArrivalType type = ArrivalType.BURSTS;
			String container = "prod_cons.LinkedListContainer";
			// ugly argument interpretation
			for (int i = 0; i < args.length; i++) {
				if (args[i].equals("-t"))
					testNum = Integer.parseInt(args[++i]);
				else if (args[i].equals("-i"))
					insertersNum = Integer.parseInt(args[++i]);
				else if (args[i].equals("-r"))
					removersNum = Integer.parseInt(args[++i]);
				else if (args[i].equals("-l"))
					lambda = Double.parseDouble(args[++i]);
				else if (args[i].equals("-p"))
					peakLength = Integer.parseInt(args[++i]);
				else if (args[i].equals("-b"))
					timeBetweenPeaks = Integer.parseInt(args[++i]);
				else if (args[i].equals("-c"))
					timeToRun = Integer.parseInt(args[++i]);
				else if (args[i].equals("-e"))
					extraInt = Integer.parseInt(args[++i]);
				else if (args[i].equals("-P"))
					type = ArrivalType.POISSON;
				else if (args[i].equals("-B"))
					type = ArrivalType.BURSTS;
				else if (args[i].equals("-C"))
					container = args[++i];
				else if (args[i].equals("-F"))
					superIndex = Integer.parseInt(args[++i]);
				else if (args[i].equals("-f")) {
					filename = args[++i];
				} else
					throw new RuntimeException("Wrong arguments");
			}
			TaskContainer taskContainer = (TaskContainer) Class.forName(
					container).newInstance();
			taskContainer.setConsumersNum(removersNum);
			if (type == ArrivalType.BURSTS) {
				if (filename.length() == 0) {
					filename = "./csvs/"+testNum + "_i" + insertersNum + "_r"
							+ removersNum + "_c" + timeToRun + "_C" + container
							+ "_e" + extraInt + "_B_p" + peakLength + "_b"
							+ timeBetweenPeaks + "(" + superIndex + ")"
							+ ".csv";
				}
				ResultPrinter.init(filename, testNum, insertersNum,
						removersNum, peakLength, timeBetweenPeaks, timeToRun,
						container, extraInt);
				testers.get(testNum).test(insertersNum, removersNum,
						peakLength, timeBetweenPeaks, timeToRun, taskContainer,
						extraInt);
			} else {
				if (filename.length() == 0) {
					filename = "./csvs/"+testNum + "_i" + insertersNum + "_r"
							+ removersNum + "_c" + timeToRun + "_C" + container
							+ "_e" + extraInt + "_P_l" + lambda + "("
							+ superIndex + ")" + ".csv";
				}
				ResultPrinter.init(filename, testNum, insertersNum,
						removersNum, lambda, timeToRun, container, extraInt);
				testers.get(testNum).test(insertersNum, removersNum, lambda,
						timeToRun, taskContainer, extraInt);
			}
			testers.get(testNum).accept(ResultPrinter.get());
		} catch (InterruptedException e) {
			System.out
					.println("new arguments:\n -t [test num]\n -i [inserters num]\n "
							+ "-r [removers num]\n -e [extra int value if needed]\n "
							+ "-c [time to run]\n -C [container type]\n-f [filename] -F [run number]"
							+ " -P -l [lambda] \n"
							+ " -B -p [peak length] -b [time between peaks]");
			e.printStackTrace();
		}
		System.out.println("Results are in place. Enjoy!");
	}
}
